﻿using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration.Json;
using Microsoft.Extensions.FileProviders;
using Newtonsoft.Json;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;

namespace AppClient
{
    public class MyConfigProvider : ConfigurationProvider
    {
        private string _serverAddress;
        public MyConfigProvider()
        {
            var jsonConfig = new JsonConfigurationSource();
            jsonConfig.FileProvider = new PhysicalFileProvider(Directory.GetCurrentDirectory());
            jsonConfig.Path = "appsettings.json";
            var jsonProvider = new JsonConfigurationProvider(jsonConfig);
            jsonProvider.Load();

            jsonProvider.TryGet("myconfigServer", out string serverAddress);

            if (string.IsNullOrEmpty(serverAddress))
            {
                throw new Exception("Can not find myconfigServer's address from appsettings.json");
            }

            _serverAddress = serverAddress;
        }

        /// <summary>
        /// 尝试从远程配置中心读取配置信息
        /// </summary>
        public async override void Load()
        {
            var response = "";
            try
            {
                var client = new HttpClient();
                client.BaseAddress = new Uri(_serverAddress);
                response = await client.GetStringAsync("/api/configs");

                WriteToLocal(response);
            }
            catch (Exception ex)
            {
                //write err log
                response = ReadFromLocal();
            }

            if (string.IsNullOrEmpty(response))
            {
                throw new Exception("Can not request configs from remote config center .");
            }

            var configs = JsonConvert.DeserializeObject<List<KeyValuePair<string, string>>>(response);

            Data = new ConcurrentDictionary<string, string>();

            configs.ForEach(c =>
            {
                Data.Add(c);
            });
        }

        private void WriteToLocal(string resp)
        {
            var file = Directory.GetCurrentDirectory() + "/myconfig.json";
            File.WriteAllText(file,resp);
        }

        private string ReadFromLocal()
        {
            var file = Directory.GetCurrentDirectory() + "/myconfig.json";
            return File.ReadAllText(file);
        }
    }

    public static class MyConfigBuilderExt
    {
        public static IConfigurationBuilder AddMyConfig(
            this IConfigurationBuilder builder
            )
        {
            return builder.Add(new MyConfigSource());
        }
    }

    public class MyConfigSource : IConfigurationSource
    {
        public IConfigurationProvider Build(IConfigurationBuilder builder)
        {
            return new MyConfigProvider();
        }
    }

}
